/*
 * Copyright © 2017 eqxiu.com 北京中网易企秀科技有限公司  All rights reserved.
 */
package cn.hermit.data.xml.validator;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import cn.hermit.data.exception.ValidationException;
import cn.hermit.util.StringUtils;
import cn.hermit.data.xml.XML;
import cn.hermit.data.xml.XmlChar;

/**
 * Default validator for basic XML string validation.
 * 
 * @author Jack Gao (Chinese name : GAO JIANGUO, Email : linux.gjg@gmail.com)
 * @date 19 Jun, 2014
 */
public final class DefaultValidator implements Validator {

	/**
	 * Indicate if keep null tags, keys, values or texts.
	 */
	protected boolean keepNull = true;

	/**
	 * Indicate if replace invalid characters in XML string.
	 */
	protected boolean replaceInvalid = true;

	/**
	 * Indicate the placeholder of invalid characters in XML string.
	 */
	protected String placeHolder = XmlChar.DEFAULT_NAME_SPECAIL_REPLACER;

	/**
	 * Indicate if need to escape XML entity symbols.
	 */
	protected boolean needEscapeXMLEntity = true;

	@Override
	public QName validateQName(QName name) throws ValidationException {
		if (name == null || StringUtils.isEmpty(name.getLocalPart())) {
			if (keepNull) {
				return new QName(XMLConstants.NULL_NS_URI,
						XML.DEFAULT_NULL_VALUE, XMLConstants.DEFAULT_NS_PREFIX);
			}
			throw new ValidationException("XML name can not be empty!");
		}
		String prefix = XmlChar.validateName(name.getPrefix(), replaceInvalid,
				placeHolder);
		String localPart = XmlChar.validateName(name.getLocalPart(),
				replaceInvalid, placeHolder);
		String ns = XmlChar
				.validateText(name.getNamespaceURI(), replaceInvalid);
		return new QName(ns, localPart, prefix);
	}

	@Override
	public Object validateValue(Object value) throws ValidationException {
		if (value == null) {
			if (keepNull) {
				return null;
			}
		}
		if (value != null && String.class.isInstance(value)) {
			value = XmlChar.validateText(value.toString(), replaceInvalid);
			if (needEscapeXMLEntity) {
				return XmlChar.escape(value.toString());
			} else {
				return value;
			}
		}
		return value;
	}

	@Override
	public Object validateText(Object text) throws ValidationException {
		return validateValue(text);
	}

	@Override
	public Object validateCData(Object cdata) throws ValidationException {
		if (cdata == null) {
			if (keepNull) {
				return null;
			}
			return XML.DEFAULT_EMPTY_VALUE;
		}
		if (String.class.isInstance(cdata)) {
			return XmlChar.validateText(cdata.toString(), replaceInvalid);
		}
		return cdata;
	}

	/**
	 * @return the keepNull
	 */
	public boolean isKeepNull() {
		return keepNull;
	}

	/**
	 * @param keepNull
	 *            the keepNull to setHeader
	 */
	public void setKeepNull(boolean keepNull) {
		this.keepNull = keepNull;
	}

	/**
	 * @return the replaceInvalid
	 */
	public boolean isReplaceInvalid() {
		return replaceInvalid;
	}

	/**
	 * @param replaceInvalid
	 *            the replaceInvalid to setHeader
	 */
	public void setReplaceInvalid(boolean replaceInvalid) {
		this.replaceInvalid = replaceInvalid;
	}

	/**
	 * @return the placeHolder
	 */
	public String getPlaceHolder() {
		return placeHolder;
	}

	/**
	 * @param placeHolder
	 *            the placeHolder to setHeader
	 */
	public void setPlaceHolder(String placeHolder) {
		this.placeHolder = placeHolder;
	}

	/**
	 * @return the needEscapeXMLEntity
	 */
	public boolean isNeedEscapeXMLEntity() {
		return needEscapeXMLEntity;
	}

	/**
	 * @param needEscapeXMLEntity
	 *            the needEscapeXMLEntity to setHeader
	 */
	public void setNeedEscapeXMLEntity(boolean needEscapeXMLEntity) {
		this.needEscapeXMLEntity = needEscapeXMLEntity;
	}

}